package com.alisiwei.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Date;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;


/**
 * 描述：webservice工具类
 * 作者：zhangkai
 * 日期：2017-8-18
 */
public class WebServiceUtil {
	private static SSLContext sslContext;
	private static Logger logger = Logger.getLogger(WebServiceUtil.class);  
	
	/**
	 * 描述：发送请求（http post方式）
	 * 作者：zhangkai
	 * @param data
	 * @param address
	 * @return
	 */
	public static String getHttpConnectResult(String data, String address){
		String resultData = "";
		Date requestStartDate = new Date();//初始化请求开始时间
		logger.info("http请求开始，请求地址：" + address);
		OutputStream wr = null;
		HttpURLConnection conn = null;
		try {
			URL url = new URL(address);
			conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestMethod("POST");
			conn.setConnectTimeout(60000);// 设置连接主机的超时时间
			conn.setReadTimeout(60000);// 设置从主机读取数据的超时时间
			
			// 打开和URL之间的连接
			wr = conn.getOutputStream();
			wr.write(data.getBytes("utf-8"));
			wr.flush();
			resultData = IOUtils.toString(conn.getInputStream(), "utf-8");
			Date requestEndDate = new Date();//初始化请求结束时间
			logger.info("请求完毕，耗时【"+(requestEndDate.getTime()-requestStartDate.getTime())+"ms】");
		} catch (MalformedURLException e) {
			e.printStackTrace();
			logger.info("http请求失败！请求地址不正确！请求地址：" + address);
		} catch (IOException e) {
			e.printStackTrace();
			logger.info("http请求失败！发生i/o错误，请求地址：" + address);
		} finally {
			try {
				if (wr != null) {
					wr.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return resultData;
	}
	
	/**
	 * 描述：发送请求（https post方式）
	 * 作者：zhangkai
	 * @param data
	 * @param address
	 * @param key_store_file
	 * @param key_store_pass
	 * @param trust_store_file
	 * @param trust_store_pass
	 * @return
	 */
	public static String getHttpConnectResult(String data, String address, String key_store_file, String key_store_pass, String trust_store_file, String trust_store_pass) {
		String resultData = "";
		Date requestStartDate = new Date();//初始化请求开始时间
		logger.info("http请求开始，请求地址：" + address);
		OutputStream wr = null;
		HttpsURLConnection conn = null;
		try {
			URL url = new URL(address);
			conn = (HttpsURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestMethod("POST");
			conn.setConnectTimeout(60000);// 设置连接主机的超时时间
			conn.setReadTimeout(60000);// 设置从主机读取数据的超时时间

			// 打开和URL之间的连接
			if (conn instanceof HttpsURLConnection) {
				((HttpsURLConnection) conn).setSSLSocketFactory(getSSLContext(key_store_file,key_store_pass, trust_store_file, trust_store_pass).getSocketFactory());
			}
			wr = conn.getOutputStream();
			wr.write(data.getBytes("utf-8"));
			wr.flush();
			resultData = IOUtils.toString(conn.getInputStream(), "utf-8");
			Date requestEndDate = new Date();//初始化请求结束时间
			logger.info("请求完毕，耗时【"+(requestEndDate.getTime()-requestStartDate.getTime())+"ms】");
		} catch (MalformedURLException e) {
			e.printStackTrace();
			logger.info("http请求失败！请求地址不正确！请求地址：" + address);
		} catch (IOException e) {
			e.printStackTrace();
			logger.info("http请求失败！发生i/o错误，请求地址：" + address);
		} finally {
			try {
				if (wr != null) {
					wr.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return resultData;
	}
	
	/**
	 * 描述：获取SSLContext
	 * 作者：zhangkai
	 * @return
	 */
	public static SSLContext getSSLContext(String key_store_file,String key_store_pass, String trust_store_file, String trust_store_pass) {
		long time1 = System.currentTimeMillis();
		if (sslContext == null) {
			try {
				KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
				kmf.init(getkeyStore(key_store_file, key_store_pass), key_store_pass.toCharArray());
				KeyManager[] keyManagers = kmf.getKeyManagers();

				TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
				trustManagerFactory.init(getTrustStore(trust_store_file,trust_store_pass));
				TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

				sslContext = SSLContext.getInstance("TLS");
				sslContext.init(keyManagers, trustManagers, new SecureRandom());
				HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
					public boolean verify(String hostname, SSLSession session) {
						return true;
					}
				});
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (UnrecoverableKeyException e) {
				e.printStackTrace();
			} catch (KeyStoreException e) {
				e.printStackTrace();
			} catch (KeyManagementException e) {
				e.printStackTrace();
			}
		}
		long time2 = System.currentTimeMillis();
		logger.info("SSLContext 初始化时间：" + (time2 - time1));
		return sslContext;
	}
	
	/**
	 * 描述：获取KeyStore
	 * 作者：zhangkai
	 * @return
	 */
	public static KeyStore getkeyStore(String key_store_file, String key_store_pass) {
		KeyStore keySotre = null;
		try {
			keySotre = KeyStore.getInstance("PKCS12");
			FileInputStream fis = new FileInputStream(new File(key_store_file));
			keySotre.load(fis, key_store_pass.toCharArray());
			fis.close();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return keySotre;
	}
	
	/**
	 * 描述：获取TrustStore
	 * 作者：zhangkai
	 * @return
	 * @throws IOException
	 */
	public static KeyStore getTrustStore(String trust_store_file, String trust_store_pass) throws IOException {
		KeyStore trustKeyStore = null;
		FileInputStream fis = null;
		try {
			trustKeyStore = KeyStore.getInstance("JKS");
			fis = new FileInputStream(new File(trust_store_file));
			trustKeyStore.load(fis, trust_store_pass.toCharArray());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			fis.close();
		}
		return trustKeyStore;
	}
	
	/**
     * 描述:获取 post 请求内容
     * @param request
     * @return
     * @throws IOException
     */

    public static String getRequestPostStr(HttpServletRequest request) throws IOException {
        byte buffer[] = getRequestPostBytes(request);
        String charEncoding = request.getCharacterEncoding();
        if (charEncoding == null) {
            charEncoding = "UTF-8";
        }
        return new String(buffer, charEncoding);
    }
    
    /**
     * 描述:获取 post 请求的 byte[] 数组
     * @param request
     * @return
     * @throws IOException
     */
    public static byte[] getRequestPostBytes(HttpServletRequest request) throws IOException {
        int contentLength = request.getContentLength();
        if(contentLength<0){
            return null;
        }
        byte buffer[] = new byte[contentLength];
        for (int i = 0; i < contentLength;) {

            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
                break;
            }
            i += readlen;
        }
        return buffer;
    }
}
